package org.the.gsdo.server;

import javax.persistence.EntityManagerFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.support.ChainedPersistenceExceptionTranslator;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@Import({
	DevConfiguration.class,
	ProdConfiguration.class
})
@PropertySource("classpath:/org/the/gsdo/server/gsdo.properties")
@ComponentScan(
		// scan by class names
		// I like this more than componentScan over strings which represent packages
		basePackageClasses = {
				GreetingManagerRest.class,
				GreetingManagerProd.class,
				LogAspectProd.class,
				LogAspectDev.class,
				LogAspectTest.class

		})
@EnableAspectJAutoProxy(proxyTargetClass=true)
//@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
// EnableLoadTimeWeaving > i would need javaagent ... not good; Run Configuration looses this setting
@EnableTransactionManagement(proxyTargetClass=true)
@Profile("main")
public class ApplicationConfiguration implements ApplicationContextAware {

	//-Dspring.profiles.default=main,prod

	@Autowired
	private Environment env;

	@Override
	public void setApplicationContext(ApplicationContext context)
			throws BeansException {
		System.out.println("setApplicationContext / " + context);
		BeanProvider.setContext(context);
	}

	@Bean(name="version")
	public String getVersion() {
		return env.getProperty("gsdo.version");
	}

	@Bean(name="transactionManager")
    public JpaTransactionManager getTransactionManager(@Qualifier("persistenceUnitNamer") PersistenceUnitNamer unitNamer) {
		org.springframework.orm.jpa.JpaTransactionManager manager =
				new org.springframework.orm.jpa.JpaTransactionManager();
		manager.setEntityManagerFactory(getEntityManagerFactory(unitNamer));
		return manager;
    }

	@Bean(name="entityManagerFactory")
    public EntityManagerFactory getEntityManagerFactory(@Qualifier("persistenceUnitNamer") PersistenceUnitNamer unitNamer) {
    	org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean em =
    			new org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean();
    	em.setJpaVendorAdapter(getJpaVendorAdapter());
    	em.setPersistenceUnitName(unitNamer.getUnitName());
    	em.setPersistenceXmlLocation("META-INF/persistence.xml");
    	em.afterPropertiesSet();
    	return em.getObject();
    }

    @Bean
    public PersistenceExceptionTranslator hibernateExceptionTranslator() {
    	return new ChainedPersistenceExceptionTranslator();
    }

    @Bean(name="jpaVendorAdapter")
    public org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter getJpaVendorAdapter() {
    	org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter adapter =
    			new org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter();
    	adapter.setShowSql(true);
    	adapter.setGenerateDdl(true);
    	return adapter;
    }

}
